home *** CD-ROM | disk | FTP | other *** search
- /*
- colchg.c
- */
-
- #include <stdlib.h>
- #include <stdlib.h>
- #include <math.h>
-
- #include "ge.h"
- #include "imageman.h"
- #include "dispman.h"
- #include "mainmenu.h"
-
-
- static int cmat[3][4];
-
-
- static int colchg_init(int c1,int c2,int mode)
- {
- #define F(a) (int)((a)*65536.0)
- int r1,g1,b1,r2,g2,b2;
- double n1,n2,n3,l;
- double cos_t,sin_t,l1,l2;
- // 2色をRGB要素に分解
- r1=getR(c1),g1=getG(c1),b1=getB(c1);
- r2=getR(c2),g2=getG(c2),b2=getB(c2);
- l1 = sqrt((double)(r1*r1+g1*g1+b1*b1));
- l2 = sqrt((double)(r2*r2+g2*g2+b2*b2));
- // C1からC2へ回転するときの軸を算出 (C1,C2の外積) → (n1,n2,n3)
- // 回転する角度の余弦・正弦を算出 → cos_t, sin_t
- n1=g1*b2-b1*g2, n2=b1*r2-r1*b2, n3=r1*g2-g1*r2;
- l=sqrt(n1*n1+n2*n2+n3*n3);
- if (l == 0)
- {
- n1 = 1.0, n2 = n3 = 0.0;
- cos_t=1.0, sin_t=0.0;
- }
- else
- {
- n1=n1/l, n2=n2/l, n3=n3/l;
- if (l1 == 0 || l2 == 0)
- return -1;
- cos_t = (double)(r1*r2+g1*g2+b1*b2) / (l1 * l2);
- if (cos_t <= 0.0)
- cos_t = 0.0;
- else if (cos_t > 1.0)
- cos_t = 1.0;
- sin_t = sqrt(1-cos_t*cos_t);
- }
- if (mode == 0)
- { // ★直交変換のみによる変換
- // スケーリング値を算出
- double k;
- if (l1 == 0.0)
- k = (l2 == 0.0 ? 1.0 : 50.0); // RGB各5ビットなので50で十分
- else
- k = l2 / l1;
- // 変換行列を作成
- double p = 1-cos_t;
- cmat[0][0] = F(k * (p*n1*n1+cos_t));
- cmat[0][1] = F(k * (p*n1*n2-n3*sin_t));
- cmat[0][2] = F(k * (p*n1*n3+n2*sin_t));
- cmat[0][3] = 0;
- cmat[1][0] = F(k * (p*n1*n2+n3*sin_t));
- cmat[1][1] = F(k * (p*n2*n2+cos_t));
- cmat[1][2] = F(k * (p*n2*n3-n1*sin_t));
- cmat[1][3] = 0;
- cmat[2][0] = F(k * (p*n1*n3-n2*sin_t));
- cmat[2][1] = F(k * (p*n2*n3+n1*sin_t));
- cmat[2][2] = F(k * (p*n3*n3+cos_t));
- cmat[2][3] = 0;
- }
- else if (mode == 1)
- { // ★直交変換+平行移動による変換(2色の明るさがほぼ同じ場合によい)
- if (l2 == 0.0)
- goto mode2;
- // 回転後に平行移動する変位を算出
- double m1,m2,m3;
- m1=r2/l2,m2=g2/l2,m3=b2/l2;
- m1 *= (l2-l1), m2 *= (l2-l1), m3 *= (l2-l1);
- // 変換行列を作成
- double p = 1-cos_t;
- cmat[0][0] = F(p*n1*n1+cos_t);
- cmat[0][1] = F(p*n1*n2-n3*sin_t);
- cmat[0][2] = F(p*n1*n3+n2*sin_t);
- cmat[0][3] = F(m1);
- cmat[1][0] = F(p*n1*n2+n3*sin_t);
- cmat[1][1] = F(p*n2*n2+cos_t);
- cmat[1][2] = F(p*n2*n3-n1*sin_t);
- cmat[1][3] = F(m2);
- cmat[2][0] = F(p*n1*n3-n2*sin_t);
- cmat[2][1] = F(p*n2*n3+n1*sin_t);
- cmat[2][2] = F(p*n3*n3+cos_t);
- cmat[2][3] = F(m3);
- }
- else if (mode == 2)
- { // ★平行移動のみによる変換(2色がよく似た色の場合によい)
- mode2:
- cmat[0][0] = F(1);
- cmat[0][1] = 0;
- cmat[0][2] = 0;
- cmat[0][3] = F((double)(r2-r1));
- cmat[1][0] = 0;
- cmat[1][1] = F(1);
- cmat[1][2] = 0;
- cmat[1][3] = F((double)(g2-g1));
- cmat[2][0] = 0;
- cmat[2][1] = 0;
- cmat[2][2] = F(1);
- cmat[2][3] = F((double)(b2-b1));
- }
- else if (mode == 3)
- {
- // ★RGB各要素に定数を掛ける変換(特定要素を強調したい/弱めたいときによい)
- cmat[0][0] = (r1>0 ? F((double)r2/(double)r1) : r2 > 0 ? F(50) : 0);
- cmat[0][1] = 0;
- cmat[0][2] = 0;
- cmat[0][3] = 0;
- cmat[1][0] = 0;
- cmat[1][1] = (g1>0 ? F((double)g2/(double)g1) : g2 > 0 ? F(50) : 0);
- cmat[1][2] = 0;
- cmat[1][3] = 0;
- cmat[2][0] = 0;
- cmat[2][1] = 0;
- cmat[2][2] = (b1>0 ? F((double)b2/(double)b1) : b2 > 0 ? F(50) : 0);
- cmat[2][3] = 0;
- }
- return 0;
- #undef F
- }
-
-
- static int colchg_trans(int c)
- {
- int r0,g0,b0,r,g,b;
- r0=getR(c),g0=getG(c),b0=getB(c);
- r = (cmat[0][0]*r0 + cmat[0][1]*g0 + cmat[0][2]*b0
- + cmat[0][3] + 0x8000) >> 16;
- g = (cmat[1][0]*r0 + cmat[1][1]*g0 + cmat[1][2]*b0
- + cmat[1][3] + 0x8000) >> 16;
- b = (cmat[2][0]*r0 + cmat[2][1]*g0 + cmat[2][2]*b0
- + cmat[2][3] + 0x8000) >> 16;
- r = _lim(r,0,31);
- g = _lim(g,0,31);
- b = _lim(b,0,31);
- return GRB(g,r,b);
- }
-
-
- static void colchg_hline(int x1,int x2,int y)
- {
- char *dp0 = EIMadrs(x1,y), *sp0 = EIMadrs_back(x1,y);
- void hline(int _x1, int _x2, int _y)
- {
- short *dp = (short*)dp0 + _x1 - x1, *sp = (short*)sp0 + _x1 - x1;
- for (int i=_x1; i<=_x2; i++,dp++,sp++)
- *dp = colchg_trans(*sp);
- }
- hline_func(x1,x2,y,hline);
- DMimage_hline_map(x1,x2,y,dp0);
- }
-
- static void mono_hline(int x1,int x2,int y)
- {
- char *dp0 = EIMadrs(x1,y), *sp0 = EIMadrs_back(x1,y);
- void hline(int _x1, int _x2, int _y)
- {
- short *dp = (short*)dp0 + _x1 - x1, *sp = (short*)sp0 + _x1 - x1;
- for (int i=_x1; i<=_x2; i++,dp++,sp++)
- {
- int sc = *sp;
- int r=getR(sc),g=getG(sc),b=getB(sc);
- int dg = (306*r+601*g+117*b+512)>>10;
- *dp = GRB(dg,dg,dg);
- }
- }
- hline_func(x1,x2,y,hline);
- DMimage_hline_map(x1,x2,y,dp0);
- }
-
-
- static void colchg(int col1,int col2,int method,int a)
- // a:0=色彩変換 1=モノクロ化
- {
- int ax1,ay1,ax2,ay2;
- area_getboundxy(&ax1,&ay1,&ax2,&ay2);
- int x,y;
- if (a == 0)
- {
- if (colchg_init(col1,col2,method) != 0)
- return;
- }
- for (y=ay1; y<=ay2; y++)
- {
- x = ax1 + area_chkxylen(ax1,ax2,y,YES);
- while (x<=ax2)
- {
- int l;
- if ((l = area_chkxylen(x,ax2,y,NO)) == 0)
- break;
- if (a == 0)
- colchg_hline(x,x+l-1,y);
- else
- mono_hline(x,x+l-1,y);
- x += l + area_chkxylen(x+l,ax2,y,YES);
- }
- }
- }
-
-
- static void do_colchg(int col1, int col2, int method)
- {
- bool first = YES;
- for (;;)
- {
- if (area_input(AREA_POLYGON) != 0)
- break;
- if (first)
- { EIMbackup(); first = NO; }
- colchg(col1,col2,method,0);
- }
- }
-
-
- static void do_mono()
- {
- for (;;)
- {
- if (area_input(AREA_POLYGON) != 0)
- break;
- EIMbackup();
- colchg(0,0,0,1);
- }
- }
-
- /*--------------------------------------------------------*/
- /* 色彩変換メニューの定義 */
- /*--------------------------------------------------------*/
-
- static int col1,col2;
- static int method = 0;
-
- #define MYLEN 256
-
- /*
- #define itemExec 1
- #define itemCancel 2
- #define itemCol1 4
- #define itemCol2 6
- #define itemColList 8
- #define itemRgbBar 9
- #define itemMethod 11
- #define itemHelp 12
- #define itemCmdMono 13
- */
-
- static void disp_colchgmenu(), erase_colchgmenu();
-
- #include "colchg.md"
-
- static char *help[] = {
- "[標準変換]\n\
- RGB 空間での回転+スカラー倍による変換。たいていはこれでこと足りる。",
- "[グラデ保存変換]\n\
- RGB 空間での回転+平行移動による変換。\
- 微妙なグラデーションを壊したくないときによい。",
- "[ちょびっと変換]\n\
- RGB 空間での平行移動のみによる変換。わずかな色彩変更のときによい。",
- "[RGB 掛け算変換]\n\
- RGB 各要素についての色1,色2 の比を全色に掛ける。\
- 特定の色要素を強(弱)めたいときによい。"
- };
-
- static void disp_methodhelp(int m)
- {
- int ix,iy,ixlen,iylen;
- menu_getbuttonxy(&colchgmenu, itemHelp, &ix, &iy, &ixlen, &iylen);
- grboxfill(ix,iy,ixlen,iylen,DMgetmenuplt(White),DrawNORMAL);
- ix+=4,ixlen-=16;
- iy+=4,iylen-=8;
- putmsg_width(ix,iy,ixlen,help[m],DMgetmenuplt(Black));
- }
-
- static void draw_csrs(),erase_csrs();
-
- static void disp_colchgmenu()
- {
- int ix,iy;
- menu_getbuttonxy(&colchgmenu, itemColList, &ix, &iy, NULL, NULL);
- drawPltList(ix,iy);
- drawPltCsr(pltnum);
- cols_init(&col1,&col2, &colchgmenu, itemCol1, itemCol2);
- drawCols();
- drawColCsr();
- draw_csrs();
- disp_methodhelp(menu_selector_getvar(menu_selector(&colchgmenu,selMethod)));
- }
-
- static void erase_colchgmenu()
- {
- eraseCols();
- erasePltList();
- }
-
- static void draw_csrs_sub(int col)
- {
- #if 0
- // 変換方法カーソルの描画
- int ix,iy;
- menu_getbuttonxy(&colchgmenu, itemMethod, &ix, &iy, NULL, NULL);
- grboxline(ix+24*method-4,iy-2,24,16+4,DMgetmenuplt(col),DrawNORMAL);
- #endif
- }
-
- static void draw_csrs()
- {
- draw_csrs_sub(Black);
- }
-
- static void erase_csrs()
- {
- draw_csrs_sub(COL_menu);
- }
-
- void commandColchg()
- {
- static bool first = YES;
- if (first)
- col1 = forecol, col2 = backcol, method = 0;
- first = NO;
- menu_disp(&colchgmenu);
- for (;;)
- {
- DMdispcsr(ms.x,ms.y);
- for (;;)
- {
- ms_get(&ms);
- if (ms.dx!=0||ms.dy!=0||ms.btn1!=OFF||ms.btn2!=OFF||key_chk()!=0)
- break;
- }
- DMerasecsr();
- scrollForCsr(1,1);
- if (ms.btn1 == OFFON)
- {
- int a; int ax,ay;
- a = menu_where(ms.x,ms.y,&colchgmenu, &ax,&ay,NULL);
- switch (a)
- {
- case itemExec:
- menu_erase();
- do_colchg(col1,col2,menu_selector_getvar(menu_selector(&colchgmenu,selMethod)));
- goto end;
- case itemCancel:
- goto exitloop;
- case itemCol1:
- case itemCol2:
- drawColCsr();
- cols_setcsrpos((a==itemCol1 ? 0 : 1));
- drawColCsr();
- break;
- case itemColList:
- drawPltCsr(pltnum); // erase
- pltnum = ax/16 + (ay/16)*4;
- makeupRgbBar();
- drawPltCsr(pltnum); // draw
- if (cols_getcsrpos() == 0)
- col1 = plt_getcode(pltnum);
- else
- col2 = plt_getcode(pltnum);
- makeupCols();
- break;
- case itemRgbBar:
- touchRgbBar(ax,ay,ms.btn1);
- if (cols_getcsrpos() == 0)
- col1 = plt_getcode(pltnum);
- else
- col2 = plt_getcode(pltnum);
- makeupCols();
- break;
- case itemMethod:
- erase_csrs();
- method = ax / 24;
- // disp_methodhelp(0);
- draw_csrs();
- break;
- case itemCmdMono:
- menu_erase();
- do_mono();
- goto end;
- case itemMoveMenu:
- menu_move();
- break;
- case itemSelector:
- menu_touchselector(&colchgmenu);
- disp_methodhelp(menu_selector_getvar(menu_selector(&colchgmenu,selMethod)));
- break;
- }
- }
- else if (ms.btn1 == ON)
- {
- int a; int ax,ay;
- a = menu_where(ms.x,ms.y,&colchgmenu, &ax,&ay,NULL);
- switch (a)
- {
- case itemRgbBar:
- touchRgbBar(ax,ay,ms.btn1);
- if (cols_getcsrpos() == 0)
- col1 = plt_getcode(pltnum);
- else
- col2 = plt_getcode(pltnum);
- makeupCols();
- }
- }
- if (ms.btn2 == OFFON)
- {
- int a;
- a = menu_where(ms.x,ms.y,&colchgmenu, NULL,NULL,NULL);
- if (a == OutOfMenu)
- {
- int px,py;
- px = DMimage_getx(ms.x), py = DMimage_gety(ms.y);
- drawPltCsr(pltnum); // erase
- if (mode == MODE32K)
- plt_setcode(pltnum, EIMpoint(px,py));
- else
- pltnum = EIMpoint(px,py);
- makeupPltList();
- makeupRgbBar();
- drawPltCsr(pltnum); // draw
- drawColCsr(); // erase
- if (cols_getcsrpos() == 0)
- col1 = plt_getcode(pltnum);
- else
- col2 = plt_getcode(pltnum);
- makeupCols();
- drawColCsr(); // draw
- }
- else
- break;
- }
- }
- exitloop:
- forecol = (cols_getcsrpos() == 0 ? col1 : col2);
- cols_setcsrpos(0);
- menu_erase();
- end:
- return;
- }
-